package generators;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;

public class Generators {
    
    private static final Random random = new Random();

    public static void main(String[] args) {
        double alpha = 5;
        double sigma = 0.72;
        double lambda = 2;
        int[] arr = new int[1000000];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = nextGaussian(alpha, sigma);
//            arr[i] = nextExponential(lambda);
//            arr[i] = nextUniform(1, 50);
        }
        Map<Integer, Integer> data = getSortedData(arr);
        String str = "";
        for (int key : data.keySet()) {
            System.out.println(key + " = " + data.get(key));
            str += "[" + key + ", " + data.get(key) + "], ";
        }
        System.out.println(str);
    }

    private static int nextGaussian(double alpha, double sigma) {
        double doubleVal = alpha + sigma * random.nextGaussian();
        return new BigDecimal(doubleVal).setScale(0, RoundingMode.HALF_UP).intValue();
    }

    private static int nextExponential(double lambda) {
        double u;
        // нельзя, чтобы u получилось равное 0, логарифм от нуля не существует
        while ((u = random.nextDouble()) <= 0.00001);
        double doubleVal = -1.0 / lambda * Math.log(u);
        return new BigDecimal(doubleVal).setScale(0, RoundingMode.HALF_UP).intValue();
    }
    
    private static int nextUniform(int a, int b) {
        return random.nextInt(b) + a;   
    }

    private static Map<Integer, Integer> getSortedData(int[] arr) {
        Map<Integer, Integer> data = new HashMap<Integer, Integer>();
        for (int i = 0; i < arr.length; i++) {
            if (data.containsKey(arr[i])) {
                int count = data.get(arr[i]) + 1;
                data.remove(arr[i]);
                data.put(arr[i], count);
            } else {
                data.put(arr[i], 1);
            }
        }

        SortedMap<Integer, Integer> sortedData = new TreeMap<Integer, Integer>();
        sortedData.putAll(data);

        return sortedData;
    }

}
